package com.iqiyi.pps.epg.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iqiyi.kiwi.utils.Configuration;
import com.iqiyi.kiwi.utils.HttpClientConnection;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by karkarrotxu on 2014/12/10.
 */
public final class ApiHttpRequestUtil {
    private static Logger logger = LoggerFactory.getLogger(ApiHttpRequestUtil.class);

    public static final String MESSAGE_CHANNEL_EXISTS = "Waring: Channel exists";
    public static final int HTTP_TIMEOUT = 5000;

    private ApiHttpRequestUtil() {
    }

    private static Map<String, String> transMap(Map<String, ? extends Object> map) {
        if (map == null) {
            return null;
        }
        Map<String, String> keyMap = new HashMap<String, String>();
        for (Map.Entry<String, ? extends Object> entry : map.entrySet()) {
            if (entry.getValue() != null) {
                keyMap.put(entry.getKey(), entry.getValue() + "");
            }
        }
        return keyMap;
    }

    public static JSONObject postMethod(String url, Map<String, ? extends Object> headers, Map<String, ? extends Object> params, int timeout) {
        return doPost(url, transMap(headers), transMap(params), timeout);
    }

    public static JSONObject postMethod(String url, Map<String, ? extends Object> headers, Map<String, ? extends Object> params) {
        return doPost(url, transMap(headers), transMap(params), 30000);
    }

    public static Object forceGetSucData(String url, Map<String, ? extends Object> headers, Map<String, ? extends Object> params) {
        JSONObject jsonObject = postMethod(url, headers, params);
        if (jsonObject != null) {
            if (Constants.CODE_SUC.equals(jsonObject.getString("code"))) {
                return jsonObject.get("data");
            }
        }
        return null;
    }

    public static String forceGetResponseMsg(String url, Map<String, ? extends Object> headers, Map<String, ? extends Object> params) {
        JSONObject jsonObject = postMethod(url, headers, params);
        if (jsonObject != null) {
            return jsonObject.getString("msg");
        }
        return null;
    }

    public static String forceGetResponseCode(String url, Map<String, ? extends Object> headers, Map<String, ? extends Object> params) {
        JSONObject jsonObject = postMethod(url, headers, params);
        if (jsonObject != null) {
            return jsonObject.getString("code");
        }
        return null;
    }

    public static JSONObject postMethod(String url, Map<String, ? extends Object> params) {
        return postMethod(url, null, params);
    }

    public static JSONObject getMethod(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers) {
        String returnValue = originalGet(url, params, headers);
        if (returnValue == null) {
            return null;
        }
        //simple check
        if (returnValue.startsWith("{") && returnValue.endsWith("}")) {
            return JSONObject.parseObject(returnValue);
        }
        return null;
    }

    public static JSONObject getMethod(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers, int timeOut) {
        String returnValue = originalGet(url, params, headers, timeOut);
        if (returnValue == null) {
            return null;
        }
        //simple check
        if (returnValue.startsWith("{") && returnValue.endsWith("}")) {
            return JSONObject.parseObject(returnValue);
        }
        return null;
    }

    public static String originalGet(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers, int timeOut) {
        return doGet(url, transMap(headers), transMap(params), timeOut);
    }

    public static String originalGet(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers) {
        return originalGet(url, transMap(params), transMap(headers), HTTP_TIMEOUT);
    }

    public static JSONObject getMethod(String url, Map<String, ? extends Object> params) {
        return getMethod(url, params, null);
    }

    public static Map<String, Object> getEpgHeaders() {
        Map<String, Object> headers = new HashMap<String, Object>();
        headers.put("From", "show");
        headers.put("Sign", "#f93Uc31K24()_@");
        return headers;
    }

    public static boolean channelCharge(Long qipuId, String name, long startTime, long endTime) {
        String url = Configuration.getString("channel.charge.url");
        boolean ret = false;
        Map<String, String> params = new HashMap<String, String>();
        params.put("qpid", qipuId.toString());
        params.put("makePrice", "0");
        params.put("charge", "2");
        params.put("name", name);
        params.put("liveStartTime", "" + startTime);
        params.put("liveEndTime", "" + endTime);
        logger.info("[HTTP][channelCharge][params:{}]", params.toString());
        for (int i = 0; i < 3; i++) {
            HttpClientConnection hcc = new HttpClientConnection(url, HttpClientConnection.GET_METHOD);
            hcc.setReqParams(params);
            hcc.connect();
            if (hcc.getStatus() == 200) {
                JSONObject result = JSONObject.parseObject(hcc.getBody());
                logger.info("[HTTP][channelCharge][result:{}]", result);
                if (result.getString("code").equals("A00000")) {
                    ret = true;
                    break;
                }
            }
        }

        return ret;
    }

    public static String doGet(String url, Map<String, String> headers, Map<String, String> params) {
        return doGet(url, headers, params, HTTP_TIMEOUT);
    }

    private static String doGet(String url, Map<String, String> headers, Map<String, String> params, int timeOut) {
        return doOriginal( url ,headers,params,HttpClientConnection.GET_METHOD,timeOut );
    }

    public static String originalPost(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers) {
        return originalPost(url, transMap(params), transMap(headers), HTTP_TIMEOUT);
    }

    public static String originalPost(String url, Map<String, ? extends Object> params, Map<String, ? extends Object> headers, int timeOut) {
        return doOriginalPost(url, transMap(headers), transMap(params), timeOut);
    }

    public static String doOriginalPost(String url, Map<String, String> headers, Map<String, String> params, int timeOut) {
        return doOriginal( url ,headers,params,HttpClientConnection.POST_METHOD,timeOut );
    }

    public static String doOriginal(String url, Map<String, String> headers, Map<String, String> params, int method, int timeOut) {
        Long startTime = System.currentTimeMillis();
        HttpClientConnection connection = null;
        String data = null;
        String strparams = JSON.toJSONString(params);
        for (int i = 0; i < 3; i++) {
            connection = new HttpClientConnection(url, method);
            if (headers != null && headers.size() > 0) {
                connection.setReqHeaders(headers);
            }
            if (params != null) {
                connection.setReqParams(params);
            }
            connection.setSoTimeout(timeOut);
            connection.connect();
            logger.info("[HTTP][doOriginal][url:{}][params:{}][status:{}][method:{}]", new Object[]{url, strparams, connection.getStatus(),method});
            if (connection.getStatus() == 200) {
                data = connection.getBody();
                logger.info("[HTTP][doOriginal][url={}][params={}][response:{}]", url, strparams, connection.getBody());
                break;
            }
        }
        logger.info("[HTTP][doOriginal][cost:{}]", System.currentTimeMillis() - startTime);
        return data;
    }

    public static JSONObject doPost(String url, Map<String, String> headers, Map<String, String> params) {
        return doPost(url, headers, params, HTTP_TIMEOUT);
    }


    public static JSONObject doPost(String url, Map<String, String> headers, Map<String, String> params, int timeout) {
        Long startTime = System.currentTimeMillis();
        HttpClientConnection connection = null;
        JSONObject data = null;
        for (int i = 0; i < 3; i++) {
            connection = new HttpClientConnection(url, HttpClientConnection.POST_METHOD);
            if (headers != null && headers.size() > 0) {
                connection.setReqHeaders(headers);
            }
            if (params != null) {
                connection.setReqParams(params);
            }

            connection.setSoTimeout(timeout);
            connection.connect();
            logger.info("[HTTP][doPost][url:{}][params:{}][status:{}]", new Object[]{url, JSON.toJSONString(params), connection.getStatus()});
            if (connection.getStatus() == 200) {
                logger.info("[HTTP][doPost][url={}][response:{}]", url, connection.getBody());
                try {
                    JSONObject jsonObject = JSONObject.parseObject(connection.getBody());
                    data = jsonObject;
                    break;
                } catch (Exception e) {
                    logger.error("[doPost]", e);
                }
            }
        }
        logger.info("[HTTP][doPost][cost:{}]", System.currentTimeMillis() - startTime);
        return data;
    }


    public static JSONObject doPostRawNolog(String url, String jsonParams) {
//        logger.info("[HTTP][doPostRaw][url:{}][params:{}]", new Object[]{url, jsonParams});
        JSONObject data = null;
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        try {
            httpClient = HttpClients.createDefault();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(new StringEntity(jsonParams));
            httpPost.setHeader("Content-type", "application/json");
            HttpResponse response = httpClient.execute(httpPost);
            String content = EntityUtils.toString(response.getEntity());
            JSONObject jsonObject = JSON.parseObject(content);
            data = jsonObject;
            logger.info("[HTTP][doPostRawNolog][url:{}][params:{}][response:{}]", new Object[]{url, jsonParams, jsonObject.toString()});
        } catch(Exception e) {
            logger.error("[doPostRawNolog]", e);
            return null;
        }
        return data;
    }

    public static JSONObject doPostRaw(String url, String jsonParams) {
        return JSON.parseObject(doPostRaw(url, jsonParams, null));
    }

    public static JSONArray doPostRawJSONArray(String url, String jsonParams, Map<String, String> headerMap) {
        return JSON.parseArray(doPostRaw(url, jsonParams, headerMap));
    }

    public static String doPostRaw(String url, String jsonParams, Map<String, String> headerMap) {
        logger.info("[HTTP][doPostRaw][url:{}][params:{}]", new Object[]{url, jsonParams});
        String data = null;
        CloseableHttpClient httpClient = null;
        HttpPost httpPost = null;
        try {
            httpClient = HttpClients.createDefault();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(20000).setConnectTimeout(20000).build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            httpPost.setEntity(new StringEntity(jsonParams));
            if (headerMap != null) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.setHeader(entry.getKey(), entry.getValue());
                }
            }
            httpPost.setHeader("Content-type", "application/json");
            HttpResponse response = httpClient.execute(httpPost);
            data = EntityUtils.toString(response.getEntity());
            logger.info("[HTTP][doPostRaw][url:{}][params:{}][response:{}]", new Object[]{url, jsonParams, data});
        } catch(Exception e) {
            logger.error("[doPostRaw]", e);
            return null;
        } finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                logger.error("[doPostRaw]", e);
            }
        }
        return data;
    }

}
